package cn.green.core.components.entity;

import cn.green.core.model.QField;
import cn.green.core.model.QTable;
import lombok.Data;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author wang.yishu
 * @version 1.0
 * @className JoinInfo
 * @description 表联接信息
 * @date 2025/3/20 08:38
 */
@Data
public class JoinInfo {
    //表连接类型
    public enum JoinType {
        LEFT, RIGHT, INNER
    }
    @Data
    public static class JoinField {
        private QField primaryTableField;//主表关联字段
        private QField foreignTableField;//外表关联字段
    }

    protected JoinType joinType;
    protected QTable foreignTable;
    protected String foreignTableAliasName;
    protected List<JoinField> joinFields;
    protected List<QField> foreignFields;

    /**
     * 整理左联数据
     * @param primaryData   主表数据
     * @param joinData      连接数据
     * @return 整理后数据
     */
    public List<Map<String, Object>> rangeLeftJoinData(List<Map<String, Object>> primaryData, List<Map<String, Object>> joinData) {
        if (primaryData == null || primaryData.isEmpty() || joinFields == null || joinFields.isEmpty() || joinData == null || joinData.isEmpty()) {
            return primaryData;
        }
        //左联，以左表为基准
        for (Map<String, Object> primaryDatum : primaryData) {
            List<Map<String, Object>> collect = joinData.stream().filter(foreignDatum -> {
                boolean found = true;
                for (JoinField joinField : joinFields) {
                    //主表的键
                    QField primaryTableField = joinField.getPrimaryTableField();
                    //主表的字段数据
                    Object primaryFieldValue = primaryDatum.get(primaryTableField.getSelectColumnName());

                    //外表的键
                    QField foreignTableField = joinField.getForeignTableField();
                    //外表的字段数据
                    Object foreignFieldValue = foreignDatum.get(foreignTableField.getFieldName());
                    found = Objects.equals(primaryFieldValue, foreignFieldValue);
                    if (!found) {
                        break;
                    }
                }
                return found;
            }).collect(Collectors.toList());
            if (!collect.isEmpty()) {
                Map<String, Object> foreignData = collect.get(0);
                foreignData.keySet().forEach((foreignField) -> {
                    primaryDatum.put(this.foreignTableAliasName + "." + foreignField, foreignData.get(foreignField));
                });
            }
        }
        return primaryData;
    }

    /**
     * 整理右联数据
     * @param primaryData   主表数据
     * @param joinData      连接数据
     * @return  整理后数据
     */
    public List<Map<String, Object>> rangeRightJoinData(List<Map<String, Object>> primaryData, List<Map<String, Object>> joinData) {
        if (primaryData == null || primaryData.isEmpty() || joinFields == null || joinFields.isEmpty() || joinData == null || joinData.isEmpty()) {
            return primaryData;
        }
        //右联，以右表为基准
        for (Map<String, Object> foreignDatum : joinData) {
            List<Map<String, Object>> collect = primaryData.stream().filter(primaryDatum -> {
                boolean found = true;
                for (JoinField joinField : joinFields) {
                    //主表的键
                    QField primaryTableField = joinField.getPrimaryTableField();
                    //主表的字段数据
                    Object primaryFieldValue = primaryDatum.get(primaryTableField.getSelectColumnName());
                    //外表的键
                    QField foreignTableField = joinField.getForeignTableField();
                    //外表的字段数据
                    Object foreignFieldValue = foreignDatum.get(foreignTableField.getFieldName());
                    found = Objects.equals(primaryFieldValue, foreignFieldValue);
                    if (!found) {
                        break;
                    }
                }
                return found;
            }).collect(Collectors.toList());
            if (!collect.isEmpty()) {
                Map<String, Object> pData = collect.get(0);
                foreignDatum.forEach((foreignField, value) -> {
                    pData.put(this.foreignTableAliasName + "." + foreignField, value);
                });
            } else {
                Map<String, Object> newForeignData = new HashMap<>();
                foreignDatum.forEach(
                        (foreignField, value) -> {
                            newForeignData.put(this.foreignTableAliasName + "." + foreignField, value);
                        }
                );
                primaryData.add(newForeignData);
            }
        }
        return primaryData;
    }

    /**
     * 整理内联数据
     * @param primaryData   主表数据
     * @param joinData      连接数据
     * @return  整理后数据
     */
    public List<Map<String, Object>> rangeInnerJoinData(List<Map<String, Object>> primaryData, List<Map<String, Object>> joinData) {
        if ((primaryData == null || primaryData.isEmpty()) || (joinData == null || joinData.isEmpty())) {
            return new ArrayList<>();
        }
        if (joinFields == null || joinFields.isEmpty()) {
            return primaryData;
        }
        //内联
        List<Map<String, Object>> rtn = new ArrayList<>();
        for (Map<String, Object> primaryDatum : primaryData) {
            List<Map<String, Object>> collect = joinData.stream().filter(foreignDatum -> {
                boolean found = true;
                for (JoinField joinField : joinFields) {
                    //主表的键
                    QField primaryTableField = joinField.getPrimaryTableField();
                    //主表的字段数据
                    Object primaryFieldValue = primaryDatum.get(primaryTableField.getSelectColumnName());

                    //外表的键
                    QField foreignTableField = joinField.getForeignTableField();
                    //外表的字段数据
                    Object foreignFieldValue = foreignDatum.get(foreignTableField.getFieldName());
                    found = Objects.equals(primaryFieldValue, foreignFieldValue);
                    if (!found) {
                        break;
                    }
                }
                return found;
            }).collect(Collectors.toList());
            if (!collect.isEmpty()) {
                Map<String, Object> foreignData = collect.get(0);
                foreignData.keySet().forEach((foreignField) -> {
                    primaryDatum.put(this.foreignTableAliasName + "." + foreignField, foreignData.get(foreignField));
                });
                rtn.add(primaryDatum);
            }
        }
        return rtn;
    }

}
